using CoreManager.Models.Entities;
using System.Data;
using System.Linq.Expressions;

namespace CoreManager.Repository.Repositories
{
    /// <summary>
    /// Dapper仓储接口
    /// 继承自通用仓储接口，提供Dapper特有的功能
    /// </summary>
    /// <typeparam name="T">实体类型，必须继承自BaseEntity</typeparam>
    public interface IDapperRepository<T> : IRepository<T> where T : BaseEntity, new()
    {
        /// <summary>
        /// 获取数据库连接
        /// </summary>
        IDbConnection Connection { get; }

        /// <summary>
        /// 执行查询并返回指定类型的结果
        /// </summary>
        /// <typeparam name="TResult">返回类型</typeparam>
        /// <param name="sql">SQL语句</param>
        /// <param name="param">参数</param>
        /// <param name="transaction">事务</param>
        /// <param name="commandTimeout">超时时间</param>
        /// <returns>查询结果</returns>
        Task<IEnumerable<TResult>> QueryAsync<TResult>(string sql, object? param = null, IDbTransaction? transaction = null, int? commandTimeout = null);

        /// <summary>
        /// 执行查询并返回单个结果
        /// </summary>
        /// <typeparam name="TResult">返回类型</typeparam>
        /// <param name="sql">SQL语句</param>
        /// <param name="param">参数</param>
        /// <param name="transaction">事务</param>
        /// <param name="commandTimeout">超时时间</param>
        /// <returns>单个结果</returns>
        Task<TResult?> QuerySingleOrDefaultAsync<TResult>(string sql, object? param = null, IDbTransaction? transaction = null, int? commandTimeout = null);

        /// <summary>
        /// 执行命令
        /// </summary>
        /// <param name="sql">SQL语句</param>
        /// <param name="param">参数</param>
        /// <param name="transaction">事务</param>
        /// <param name="commandTimeout">超时时间</param>
        /// <returns>受影响的行数</returns>
        Task<int> ExecuteAsync(string sql, object? param = null, IDbTransaction? transaction = null, int? commandTimeout = null);

        /// <summary>
        /// 执行标量查询
        /// </summary>
        /// <typeparam name="TResult">返回类型</typeparam>
        /// <param name="sql">SQL语句</param>
        /// <param name="param">参数</param>
        /// <param name="transaction">事务</param>
        /// <param name="commandTimeout">超时时间</param>
        /// <returns>标量结果</returns>
        Task<TResult?> ExecuteScalarAsync<TResult>(string sql, object? param = null, IDbTransaction? transaction = null, int? commandTimeout = null);

        /// <summary>
        /// 执行存储过程
        /// </summary>
        /// <typeparam name="TResult">返回类型</typeparam>
        /// <param name="storedProcedure">存储过程名称</param>
        /// <param name="param">参数</param>
        /// <param name="transaction">事务</param>
        /// <param name="commandTimeout">超时时间</param>
        /// <returns>查询结果</returns>
        Task<IEnumerable<TResult>> QueryStoredProcedureAsync<TResult>(string storedProcedure, object? param = null, IDbTransaction? transaction = null, int? commandTimeout = null);

        /// <summary>
        /// 批量插入（使用Dapper.Contrib）
        /// </summary>
        /// <param name="entities">实体列表</param>
        /// <param name="transaction">事务</param>
        /// <returns>插入的行数</returns>
        Task<long> BulkInsertAsync(IEnumerable<T> entities, IDbTransaction? transaction = null);

        /// <summary>
        /// 批量更新（使用Dapper.Contrib）
        /// </summary>
        /// <param name="entities">实体列表</param>
        /// <param name="transaction">事务</param>
        /// <returns>是否成功</returns>
        Task<bool> BulkUpdateAsync(IEnumerable<T> entities, IDbTransaction? transaction = null);

        /// <summary>
        /// 开始事务
        /// </summary>
        /// <returns>事务对象</returns>
        IDbTransaction BeginTransaction();

        /// <summary>
        /// 多结果集查询
        /// </summary>
        /// <param name="sql">SQL语句</param>
        /// <param name="param">参数</param>
        /// <param name="transaction">事务</param>
        /// <param name="commandTimeout">超时时间</param>
        /// <returns>多结果集读取器</returns>
        Task<T1> QueryMultipleAsync<T1>(string sql, Func<Dapper.SqlMapper.GridReader, T1> map, object? param = null, IDbTransaction? transaction = null, int? commandTimeout = null);
    }
}